// import appBackLastPage from '@/services/h5/app-api/appBackLastPage.js'
//
import { configs, env, isWeChatBrowser } from '@/config/h5/index.js'
import appBackMainPage from '@/services/h5/app-api/appBackMainPage.js'
// import { isDebugMode } from '@/config/public'
import API from '@/services/h5/common'
import { encryptor, ls } from '@/utils/aes'
import { isApp } from '@/utils/platform'
import { setAuthorization } from '@/utils/request'
import axios from 'axios'
import { Base64 } from 'js-base64'
import Cookie from 'js-cookie'

const CancelToken = axios.CancelToken

var _ = require('lodash')
var toLogin = undefined

// 请求错误忽略
const reqErrorIgnore = {
  paths: [
    '/provider/token/accesstoken',
    '/provider/ams/userPrivilege/workwechat/login'
    // '/provider/ims/ejbb/wechat/code/login'
  ],
  includes(url) {
    for (const path of this.paths) {
      if (url.includes(path)) {
        return true
      }
    }
    return false
  }
}

const tokenIgnore = {
  paths: [
    'provider/ims/ejbb/firstpage/message/count/unread',
    'provider/ims/ejbb/firstpage/product/list',
    'provider/ims/ejbb/product/list'
  ],
  includes(url) {
    for (const path of this.paths) {
      if (url.includes(path)) {
        return true
      }
    }
    return false
  }
}

var isTokenFreshing = false
function fetchFreshToken(response, options) {
  console.log('fetchFreshToken => ')
  if (!isTokenFreshing) {
    isTokenFreshing = true
    console.log('rqtGetRefreshToken...')
    API.rqtGetRefreshToken()
      .then(res => {
        console.log('rqtGetRefreshToken success')
        const { store } = options
        const user = store.state.account.user
        user.refreshtoken = res.headers['refresh-token']
        const expireAt = new Date(new Date().getTime() + 24 * 60 * 60 * 1000)
        store.commit('account/setUser', user)
        store.commit('loading/setLoading', false)
        localStorage.setItem('refreshToken', res.headers['refresh-token'])
        setAuthorization({
          token: res.headers['access-token'],
          expireAt: new Date(expireAt)
        })
        onAccessTokenFetched()
        isTokenFreshing = false
      })
      .catch(error => {
        console.error('rqtGetRefreshToken error')
        onAccessTokenFetched(error)
        isTokenFreshing = false
      })
  }
  if (response.config.url.includes('token/refresh')) {
    return response
  }
  return new Promise((resolve, reject) => {
    const { config } = response
    addSubscriber(error => {
      if (error) {
        reject(error)
      } else {
        resolve(
          axios.request({
            url: config.url,
            method: config.method,
            data: config.data,
            headers: config.headers,
            timeout: config.timeout,
            withCredentials: config.withCredentials,
            // xsrfHeaderName: config.xsrfHeaderName,
            xsrfCookieName: config.xsrfCookieName,
            params: config.params,
            responseType: config.responseType,
            isNeedToken: config.isNeedToken
          })
        )
      }
    })
  })
}
var subscribers = []
function onAccessTokenFetched(error) {
  subscribers.forEach(callback => {
    callback(error)
  })
  subscribers = []
}
function addSubscriber(callback) {
  subscribers.push(callback)
}
// 业务拦截
const respCommon = {
  /**
   * 响应数据之前做点什么
   * @param response 响应对象
   * @param options 应用配置 包含: {router, i18n, store, message}
   * @returns {*}
   */
  onFulfilled(response, options) {
    const { data, config } = response
    const { message, router, store } = options
    if (response.status === 401) {
      message.error('无此接口权限')
      store.commit('loading/setLoading', false)
      return response
    }

    if (response.status === 404) {
      message.error(`Not Found`)
      store.commit('loading/setLoading', false)
      return response
    }
    if (response.status === 403) {
      message.error(`请求被拒绝`)
      store.commit('loading/setLoading', false)
      return response
    }

    if (
      response.data &&
      typeof response.data === 'string' &&
      response.request.responseType !== 'blob'
    ) {
      // response json data decrypt
      response.data = JSON.parse(Base64.decode(response.data))
    }

    if (data.code) {
      switch (data.code) {
        case 1000:
          return response
        case 3003:
          store.commit('loading/setLoading', false) // token 刷新成功
          return response
        case 3001:
          return fetchFreshToken(response, options) // access token 已经失效
        // case 3002:
        // store.commit('loading/setLoading', false) // refresh token 已经失效
        /* falls through */
        case 3002:
        case 3004: // redis 认证信息已经失效
          if (!toLogin) {
            toLogin = _.throttle(
              function () {
                !reqErrorIgnore.includes(config.url) &&
                  store.commit('loading/setLoading', false)
                if (!isApp) {
                  if (!isWeChatBrowser) {
                    message.warning('登录已失效，请重新登录')
                  } else {
                    window.location.href = configs[env].wxlogoutUrl
                  }
                  router.replace('/login').catch(err => err)
                } else {
                  appBackMainPage({
                    pageIndex: '3'
                  })
                }
              },
              2000,
              { trailing: false }
            )
          }
          toLogin()
          return Promise.reject(response)
        // case 2008:
        //   return response
        case 2008:
        default:
          if (!reqErrorIgnore.includes(config.url)) {
            if (data.msg && data.data) {
              let dataType =
                Object.prototype.toString.call(data.data) === '[object Object]' // 判断返回数据是否是对象
              if (dataType) {
                message.error(`【${data.msg}】`)
              } else {
                message.error(`【${data.msg}】：${data.data}`)
              }
            } else {
              message.error(data.msg || JSON.stringify(data))
            }
          }
          store.commit('loading/setLoading', false)
          return Promise.reject(response)
      }
    } else {
      return response
    }
  }
}
const reqCommon = {
  /**
   * 发送请求之前做些什么
   * @param config axios config
   * @param options 应用配置 包含: {router, i18n, store, message}
   * @returns {*}
   */
  onFulfilled(config, options) {
    const { message, store, router } = options
    const { url, xsrfCookieName, isNeedToken } = config
    const user = store.state.account.user
    const loginInfo = localStorage.getItem('loginKey')
    let cancel
    config.cancelToken = new CancelToken(function executor(c) {
      cancel = c
    })
    // Cookie.remove(xsrfCookieName)
    if (
      isNeedToken &&
      url.indexOf('login') === -1 &&
      xsrfCookieName &&
      (!Cookie.get(xsrfCookieName) ||
        Cookie.get(xsrfCookieName) == '' ||
        Cookie.get(xsrfCookieName) == 'undefined' ||
        !loginInfo)
    ) {
      if (!isApp) {
        router.replace('/login').catch(err => err)
        message.warning('未登录，请先登录')
        cancel()
      } else {
        appBackMainPage({
          pageIndex: '3'
        })
      }
    }
    // 设置请求头
    if (user && loginInfo) {
      try {
        let publicKey = ls.get('loginKey')
        encryptor.setPublicKey(publicKey)
        let time = new Date().getTime()
        const timeStamp = encryptor.encrypt(time.toString())
        timeStamp && (config.headers['Time-Stamp'] = timeStamp)
      } catch (e) {
        console.log('time-stamp--error')
        let publicKey = localStorage.getItem('unloginKey')
        encryptor.setPublicKey(publicKey)
        let time = new Date().getTime()
        const timeStamp = encryptor.encrypt(time.toString())
        timeStamp && (config.headers['Time-Stamp'] = timeStamp)
      }
    }

    // 首页未读消息数据，有用户登录必传token
    tokenIgnore.includes(config.url) &&
      Cookie.get(xsrfCookieName) &&
      (config.headers[xsrfCookieName] = Cookie.get(xsrfCookieName))

    !config.isNeedToken &&
      !tokenIgnore.includes(config.url) &&
      (config.headers[xsrfCookieName] = '')
    // 必须传入token的接口
    config.isNeedToken &&
      (config.headers[xsrfCookieName] = Cookie.get(xsrfCookieName))
    // refreshToken刷新
    url.indexOf('provider/token/refresh') > -1 &&
      (config.headers['Refresh-Token'] = localStorage.getItem('refreshToken'))

    return config
  }
}

export default {
  request: [reqCommon], // 请求拦截
  response: [respCommon] // 响应拦截
}
